package com.black.utils.file.compress.gz;

import com.black.utils.file.FileTypeEnum;
import com.black.utils.file.FileUtil;
import com.black.utils.file.compress.tar.TarUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.zip.GZIPOutputStream;

import static com.black.utils.file.FileUtil.BUFFER_SIZE;

/**
 * @author ylx
 */
public class GzUtil
{

    public static void toTarGz(String source)
        throws IOException
    {
        toTarGz(source, false);
    }

    public static void toTarGz(String source, boolean containsSelf)
        throws IOException
    {
        File dir = new File(source);
        toTarGz(dir, containsSelf);
    }

    public static void toTarGz(File dir, boolean containsSelf)
        throws IOException
    {
        if (!dir.isDirectory())
        {
            containsSelf = false;
        }
        String target =
            FileTypeEnum.transferExtension(dir.getAbsolutePath(), FileTypeEnum.TAR) + FileTypeEnum.GZ.getSuffix();
        List<File> list = containsSelf ? Collections.singletonList(dir) : Arrays.asList(dir.listFiles());
        toTarGz(target, list);
    }

    public static void toTarGz(File dist, File... files)
        throws IOException
    {
        toTarGz(dist.getAbsolutePath(), Arrays.asList(files));
    }

    public static void toTarGz(File dist, List<File> files)
        throws IOException
    {
        toTarGz(dist.getAbsolutePath(), files);
    }

    public static void toTarGz(String tarGzFile, List<File> srcFiles)
        throws IOException
    {
        if (!FileTypeEnum.GZ.is(tarGzFile))
        {
            throw new IllegalArgumentException("The target file name must end with .tar.gz");
        }
        String tarFile = FileTypeEnum.getPrefix(tarGzFile);
        if (!FileTypeEnum.TAR.is(tarFile))
        {
            throw new IllegalArgumentException("The target file name must end with .tar.gz");
        }
        File file = new File(tarFile);
        TarUtil.toTar(file, srcFiles);
        tarToGz(file);
        FileUtil.remove(file);
    }

    public static void tarToGz(String tarFile)
        throws IOException
    {
        tarToGz(tarFile, tarFile + FileTypeEnum.GZ.getSuffix());
    }

    public static void tarToGz(File tarFile)
        throws IOException
    {
        tarToGz(tarFile, new File(tarFile.getAbsolutePath() + FileTypeEnum.GZ.getSuffix()));
    }

    public static void tarToGz(String tarFile, String tarGzFile)
        throws IOException
    {
        tarToGz(new File(tarFile), new File(tarGzFile));
    }

    public static void tarToGz(String tarFile, File tarGzFile)
        throws IOException
    {
        tarToGz(new File(tarFile), tarGzFile);
    }

    public static void tarToGz(File tarFile, String tarGzFile)
        throws IOException
    {
        tarToGz(tarFile, new File(tarGzFile));
    }

    /**
     * 将 .tar 文件压缩为 .tar.gz 文件
     *
     * @param tarFile   要压缩的 .tar 文件
     * @param tarGzFile 输出的 .tar.gz 文件
     * @throws IOException IO异常
     */
    public static void tarToGz(File tarFile, File tarGzFile)
        throws IOException
    {
        try (FileInputStream fis = new FileInputStream(tarFile);
             FileOutputStream fos = new FileOutputStream(tarGzFile);
             GZIPOutputStream gzipOut = new GZIPOutputStream(fos))
        {
            if (!tarFile.exists())
            {
                throw new IllegalArgumentException("File does not exist: " + tarFile);
            }
            if (tarGzFile.exists())
            {
                tarGzFile.delete();
            }
            tarGzFile.createNewFile();
            byte[] buffer = new byte[BUFFER_SIZE];
            int length;
            while ((length = fis.read(buffer)) > 0)
            {
                gzipOut.write(buffer, 0, length);
            }
        }
    }
}
